import re
import datetime
import time
import asyncio
import random
import telethon
import os
import logging

from ..db import DB
from ..utils import Color

from tqdm import trange

from telethon.tl.functions.channels import LeaveChannelRequest
from telethon.tl.types import PeerChannel


def setup_logging():
    file_log = logging.FileHandler(
        os.path.join(os.getcwd(), "./CryptoFarm/logs/Log.log")
    )
    console_out = logging.StreamHandler()

    logging.basicConfig(
        handlers=(file_log, console_out),
        level=logging.INFO,
        format=Color.Blue
        + "%(filename)s"
        + Color.Red
        + "[LINE:%(lineno)d]"
        + Color.Clear
        + "# %(levelname)-8s"
        + Color.Yellow
        + "[%(asctime)s]"
        + "%(message)s",
        datefmt="%m.%d.%Y %H:%M:%S",
    )
    return logging


def check_href_or_id(string):
    if re.findall("https://", string):

        def fn():
            return string

        return fn
    else:

        def fn():
            return PeerChannel(int(string))

        return fn


class BasicSchema:
    CONST_SORRY_SLEEP = 1650
    CONST_ROUNDS_TO_SLEEP = 320
    CONST_NAMED_BOT = "LTC"
    round_loop = 0
    sorry_round = 0
    total_sorry_round = 0

    async def rand_sleep(self, a, b, division=100):
        for i in trange(division):  # Деление
            await asyncio.sleep(random.randint(a, b) / division)

    IDX_dlgs = []

    def __init__(self, client, new_client, turple_rounds, CONST_NAMED_BOT):
        self.logging = setup_logging()
        self.client = client[0]
        self.tegmo = client[-1]
        self.new_client = new_client
        self.round_loop = turple_rounds[0]
        self.total_sorry_round = turple_rounds[-1]
        self.type = "visits"
        self.CONST_NAMED_BOT = CONST_NAMED_BOT

    async def save_current_dialogs(self):
        dlgs = await self.client.get_dialogs()
        for dlg in dlgs:
            self.IDX_dlgs.append(dlg.id)

    async def withdraw(self):
        # Не совсем ясно как работают новые старые и для совмествимости адреса,
        # И сколько живет привидущий адрес
        async with self.client.conversation(
            f"{self.CONST_NAMED_BOT} Click Bot"
        ) as conv:
            # Узнаем баланс чтобы потом решить можем мы снять или нет
            await conv.send_message("/balance")
            try:
                msg = await conv.get_response()
            except DeprecationWarning:
                pass
            balance = float(re.findall(r"([0-9].[0-9]+)", msg.text)[-1])
            if balance < 0.00040000:
                return
            await self.rand_sleep(1, 3)
            await conv.send_message("/withdraw")
            try:
                await conv.get_response()
            except DeprecationWarning:
                pass
            await self.rand_sleep(1, 1)
            # Забираем из окружения кошелек и скармливаем боту
            await conv.send_message(os.getenv("LTC_WALLET"))
            try:
                await conv.get_response()
            except DeprecationWarning:
                pass
            await self.rand_sleep(1, 3)
            await conv.send_message(f"{balance}")
            try:
                await conv.get_response()
            except DeprecationWarning:
                pass
            # Подтверждаем транзакцию
            await conv.send_message("✅ Confirm")

    async def delay_exit_from_chat(self, delay, id, dbpointer):
        # Спим наш делей
        await asyncio.sleep(delay)
        entity = await self.client.get_entity(PeerChannel(int(id)))
        await self.client(LeaveChannelRequest(entity))
        await DB.delete_channel(dbpointer)
        # Удалили из дб, записали лог
        self.logging.info(f"Delete from db {dbpointer}")

    async def exclude_expire_chats(self):
        # Обозначаем переменные для статистики и интереса)
        counter = 0
        in_time = time.time()
        self.logging.info("added channels for list")
        chats = await DB.get_channels()
        for chat in chats:
            # В стринг храниться строка с ссылкой канала и датой выхода
            chat = chat["String"]
            counter += 1  # Возможно нужно поменять тип обращения к каналу чтобы хитрожопые индусы не меняли url и акк не оставался в чате
            self.logging.info("Next chat")
            id, expire = chat.split("|")  # Делим стринг
            pre_entity = check_href_or_id(id)()
            expire = datetime.datetime.strptime(
                expire.split(".")[0], "%Y-%m-%d %H:%M:%S"
            )
            if datetime.datetime.now() > expire:
                self.logging.info(f"Exit from channel {pre_entity}")
                for i in trange(100):
                    await asyncio.sleep(3 / 100)
                try:
                    entity = await self.client.get_entity(pre_entity)
                except:
                    self.logging.info("Cant get entity")
                    await DB.delete_channel(chat)
                    continue
                self.logging.info("Successful get entity")
                await asyncio.sleep(0.5)
                try:
                    await self.client(LeaveChannelRequest(entity))
                except:
                    self.logging.info("Error while exit from channel")
                self.logging.info("Telegram transation successful")
                await DB.delete_channel(chat)
                continue
            exptime = expire - datetime.datetime.now()
            self.logging.info(f"Exptime - {exptime.total_seconds()}")
            # Создаем задачу для машины состояний asyncio
            self.client.loop.create_task(
                self.delay_exit_from_chat(exptime.total_seconds(), id, chat)
            ).set_name("expire_chat")
            self.logging.info("Exptime Task created.")
            continue
        out_time = time.time()
        # Класный снипет
        self.logging.info(
            f"Finish work with channels {(out_time-in_time):.2f}s, all channels - {counter}"
        )
